package com.eastfair.certificate.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.auth.entity.UserOrganization;
import com.eastfair.boot.request.PageParams;
import com.eastfair.certificate.dao.BlacklistMapper;
import com.eastfair.certificate.entity.Blacklist;
import com.eastfair.certificate.entity.CertificateUser;
import com.eastfair.certificate.enumeration.BlacklistKindEnum;
import com.eastfair.certificate.service.BlacklistService;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.certificate.service.CertificateUserService;
import com.eastfair.core.context.ContextConstants;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.database.mybatis.typehandler.TypeHandlerUtil;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;

import java.util.*;

//import com.baomidou.dynamic.datasource.annotation.DS;
import org.springframework.aop.framework.AopContext;
import com.eastfair.annotation.annotation.cache.Magic;
import com.eastfair.annotation.annotation.cache.Cache;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.util.stream.Collectors;

import com.eastfair.certificate.vo.*;
import com.eastfair.certificate.dto.*;

/**
 * <p>
 * 业务实现类
 *
 * </p>
 *
 * @author clm
 * @date 2022-08-02
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class BlacklistServiceImpl extends SuperServiceImpl<BlacklistMapper, Blacklist> implements BlacklistService {

    @Autowired
    CertificateUserService certificateUserService;


    @Override
    protected R<Boolean> handlerSave(Blacklist model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        //雪花ID
        return R.successDef();
    }

    /**
     * 处理新增之后的相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSaveBack(Blacklist model) {
        return R.successDef();
    }

    /**
     * 处理修改之后的相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerUpdateByIdBack(Blacklist model) {
        return R.successDef();
    }


    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<Blacklist> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }

    /**
     * 通用查询
     *
     * @param modelDTO DTO
     * @param ids      主键id集合
     * @return list
     */
    @Override
    public List<Blacklist> list(BlacklistDTO modelDTO, List<Long> ids) {
        return ((BlacklistService) AopContext.currentProxy()).listOfCache(modelDTO, ids);
    }


    /**
     * 缓存查询
     *
     * @param modelDTO DTO
     * @param ids      主键id集合
     * @return list
     */
    @Override
    @Cache(key = "",
            magic = @Magic(
                    key = "{" +
                            "{'isEnabled', #args[0]?.isEnabled}," +
                            "{'exhibitionId', #args[0]?.exhibitionId}," +
                            "{'exhibitionName', #args[0]?.exhibitionName}," +
                            "{'cardNumber', #args[0]?.cardNumber}," +
                            "{'phoneNumber', #args[0]?.phoneNumber}," +
                            "{'companyName', #args[0]?.companyName}," +
                            "{'companyId', #args[0]?.companyId}," +
                            "{'remark', #args[0]?.remark}," +
                            "{'kind', #args[0]?.kind}," +
                            "{'id', #args[1]}" +
                            "}"))
    public List<Blacklist> listOfCache(BlacklistDTO modelDTO, List<Long> ids) {
        //查询
        QueryWrapper<Blacklist> queryWrapper = new QueryWrapper<>();
        if (modelDTO != null) {
            queryWrapper.lambda().eq(modelDTO.getExhibitionId() != null, Blacklist::getExhibitionId, modelDTO.getExhibitionId());
            queryWrapper.lambda().eq(StringUtils.isNotBlank(modelDTO.getExhibitionName()), Blacklist::getExhibitionName, modelDTO.getExhibitionName());
            queryWrapper.lambda().eq(StringUtils.isNotBlank(modelDTO.getCardNumber()), Blacklist::getCardNumber, TypeHandlerUtil.crypt(modelDTO.getCardNumber()));
            queryWrapper.lambda().eq(StringUtils.isNotBlank(modelDTO.getPhoneNumber()), Blacklist::getPhoneNumber, TypeHandlerUtil.crypt(modelDTO.getPhoneNumber()));
            queryWrapper.lambda().eq(StringUtils.isNotBlank(modelDTO.getCompanyName()), Blacklist::getCompanyName, modelDTO.getCompanyName());
            queryWrapper.lambda().eq(modelDTO.getCompanyId() != null, Blacklist::getCompanyId, modelDTO.getCompanyId());
            queryWrapper.lambda().eq(StringUtils.isNotBlank(modelDTO.getRemark()), Blacklist::getRemark, modelDTO.getRemark());
            queryWrapper.lambda().eq(modelDTO.getKind() != null, Blacklist::getKind, modelDTO.getKind());
        }
        if (ids != null && !ids.isEmpty()) {
            queryWrapper.lambda().in(Blacklist::getId, ids);
        }
        queryWrapper.lambda().eq(Blacklist::getIsDeleted, BusinessConstant.DELETE_NO);
        List<Blacklist> modelList = list(queryWrapper);
        return modelList;
    }

    /**
     * @param params
     * @return
     * @Author clm
     * @Description //分页查询
     * @Date 11:25 2022/8/2
     * @Param [params]
     */
    @Override
    public Page<BlacklistVO> queryPage(PageParams<BlacklistPageQuery> params) {
        BlacklistPageQuery model = params.getModel();

        LambdaQueryWrapper<Blacklist> blacklistLambdaQueryWrapper = new LambdaQueryWrapper<>();
        blacklistLambdaQueryWrapper.eq(Blacklist::getKind, model.getKind());

        blacklistLambdaQueryWrapper.eq(model.getExhibitionId() != null, Blacklist::getExhibitionId, model.getExhibitionId());
        blacklistLambdaQueryWrapper.like(StrUtil.isNotBlank(model.getExhibitionName()), Blacklist::getExhibitionName, "%" + model.getExhibitionName() + "%");
        blacklistLambdaQueryWrapper.eq(StrUtil.isNotBlank(model.getPhoneNumber()), Blacklist::getPhoneNumber, model.getPhoneNumber());
        blacklistLambdaQueryWrapper.eq(model.getCompanyId() != null, Blacklist::getCompanyId, model.getCompanyId());
        blacklistLambdaQueryWrapper.like(StrUtil.isNotBlank(model.getCompanyName()), Blacklist::getCompanyName, "%" + model.getCompanyName() + "%");
        blacklistLambdaQueryWrapper.like(StrUtil.isNotBlank(model.getCardNumber()), Blacklist::getCardNumber, "%" + model.getCardNumber() + "%");
        blacklistLambdaQueryWrapper.like(StrUtil.isNotBlank(model.getUserName()), Blacklist::getUserName, "%" + model.getUserName() + "%");
        blacklistLambdaQueryWrapper.eq(Blacklist::getIsEnabled, BusinessConstant.ENABLE_YES);
        //参数转化
        Page<Blacklist> blackPage = params.buildPage();
        //查询
        Page<Blacklist> blacklistPage = page(blackPage, blacklistLambdaQueryWrapper);
        //实体转化
        Page<BlacklistVO> blacklistVOPage = ConvertUtil.convertPage(blacklistPage, BlacklistVO.class);
        return blacklistVOPage;
    }

    /**
     * @param blackId
     * @return void
     * @Author clm
     * @Description //取消
     * @Date 11:56 2022/8/2
     * @Param [blackId]
     */
    @Override
    public void cancel(Long blackId) {
        Blacklist blacklist = getById(blackId);
        blacklist.setIsEnabled(BusinessConstant.ENABLE_NO);
        updateById(blacklist);
    }

    /**
     * @param cardNumber
     * @param exhibitionId
     * @return java.lang.Boolean
     * @Author clm
     * @Description //是否黑名单里
     * @Date 10:15 2022/8/6
     * @Param []
     */
    @Override
    public Boolean isInBlackList(String cardNumber, Long exhibitionId, String phoneNumber, Long companyId) {
        LambdaQueryWrapper<Blacklist> blacklistLambdaQueryWrapper = new LambdaQueryWrapper<>();
        blacklistLambdaQueryWrapper.and(wrapper -> {
            if (StringUtils.isNotBlank(cardNumber)) {
                wrapper.eq(Blacklist::getCardNumber, TypeHandlerUtil.crypt(cardNumber));
                wrapper.or();
            }
            if (StringUtils.isNotBlank(phoneNumber)) {
                wrapper.in(Blacklist::getPhoneNumber, TypeHandlerUtil.crypt(phoneNumber));
                wrapper.or();
            }
            if (companyId != null) {
                wrapper.eq(Blacklist::getCompanyId, companyId);
                wrapper.or();
            }
        });
        blacklistLambdaQueryWrapper.eq(Blacklist::getIsDeleted, BusinessConstant.NO);
        blacklistLambdaQueryWrapper.eq(Blacklist::getIsEnabled, BusinessConstant.ENABLE_YES);
        List<Blacklist> blacklists = baseMapper.selectList(blacklistLambdaQueryWrapper);
        if (CollectionUtil.isEmpty(blacklists)) {
            return Boolean.FALSE;
        }

        for (Blacklist blacklist : blacklists) {
            //判断场馆黑名单
            if (BlacklistKindEnum.POLICE.eq(blacklist.getKind()) ||
                    BlacklistKindEnum.VENUE.eq(blacklist.getKind())) {
                return Boolean.TRUE;
            }
            //判断展会黑名单
            if (BlacklistKindEnum.EXHIBITION.eq(blacklist.getKind())
                    && exhibitionId != null
                    && blacklist.getExhibitionId() != null
                    && exhibitionId.equals(blacklist.getExhibitionId())) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    @Override
    public void removeBlack(List<Long> blackIds) {
        List<Blacklist> blacklists = list(null, blackIds);
        if (CollectionUtil.isEmpty(blacklists)) {
            return;
        }
        for (Blacklist blacklist : blacklists) {
            blacklist.setIsDeleted(BusinessConstant.YES);
            updateById(blacklist);
        }
        //同步到制证
        Map<BlacklistKindEnum, List<Blacklist>> map = findBlackList(null);
        //执行操作
        executeRemove(map, blacklists, blacklists.get(0).getKind());
    }

    /**
     * 进行删除操作
     *
     * @param map        全部数据
     * @param blacklists 需要删除的数据
     */
    public void executeRemove(Map<BlacklistKindEnum, List<Blacklist>> map, List<Blacklist> blacklists, BlacklistKindEnum blacklistKindEnum) {
        //公安黑名单
        List<Blacklist> policeBlackList = new ArrayList<>();
        //场馆黑名单
        List<Blacklist> venueBlackList = new ArrayList<>();
        //展会黑名单
        List<Blacklist> exhibitionBlackList = new ArrayList<>();
        if (map != null) {
            policeBlackList = map.get(BlacklistKindEnum.POLICE);
            //场馆黑名单
            venueBlackList = map.get(BlacklistKindEnum.VENUE);
            //展会黑名单
            exhibitionBlackList = map.get(BlacklistKindEnum.EXHIBITION);
        }
        List<Blacklist> allBlackList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(policeBlackList)) {
            allBlackList.addAll(policeBlackList);
        }
        if (CollectionUtil.isNotEmpty(venueBlackList)) {
            allBlackList.addAll(venueBlackList);
        }

        if (BlacklistKindEnum.POLICE.eq(blacklistKindEnum) || BlacklistKindEnum.VENUE.eq(blacklistKindEnum)) {
            blacklists = filterBlackList(blacklists, allBlackList);
            log.info("需要删除的黑名单 is {}", JSONObject.toJSONString(blacklists));
            if (CollectionUtil.isNotEmpty(blacklists)) {
                for (Blacklist blacklist : blacklists) {

                    //过滤出在展会黑名单数据
                    List<Blacklist> exhibitionBlackList2 = null;
                    if (CollectionUtil.isNotEmpty(exhibitionBlackList)) {
                        exhibitionBlackList2 = exhibitionBlackList.stream().filter(s -> {
                            if (StringUtils.isNotBlank(blacklist.getPhoneNumber()) && blacklist.getPhoneNumber().equals(s.getPhoneNumber())) {
                                return true;
                            }
                            if (StringUtils.isNotBlank(blacklist.getCardNumber()) && blacklist.getCardNumber().equals(s.getCardNumber())) {
                                return true;
                            }

                            if (blacklist.getCompanyId() != null && blacklist.getCompanyId().equals(s.getCompanyId())) {
                                return true;
                            }
                            return false;
                        }).collect(Collectors.toList());
                    }

                    certificateUserService.sycnRemoveBackSertificate(
                            StringUtils.isNotBlank(blacklist.getPhoneNumber()) ? Arrays.asList(blacklist.getPhoneNumber()) : null,
                            StringUtils.isNotBlank(blacklist.getCardNumber()) ? Arrays.asList(blacklist.getCardNumber()) : null,
                            blacklist.getCompanyId() != null ? Arrays.asList(blacklist.getCompanyId()) : null,
                            null,
                            CollectionUtil.isNotEmpty(exhibitionBlackList2) ? exhibitionBlackList2.stream().map(Blacklist::getExhibitionId).collect(Collectors.toList()) : null);
                }


            }
        } else if (BlacklistKindEnum.EXHIBITION.eq(blacklistKindEnum)) {
            //既要过滤公安黑名单和展馆黑名单，还要过滤展会黑名单
            blacklists = filterBlackList(blacklists, allBlackList);
            blacklists = filterBlackList(blacklists, exhibitionBlackList);
            log.info("需要删除的黑名单 is {}", JSONObject.toJSONString(blacklists));
            if (CollectionUtil.isNotEmpty(blacklists)) {
                Map<Long, List<Blacklist>> goupbyMap = blacklists.stream().collect(Collectors.groupingBy(s -> s.getExhibitionId()));
                for (Long exhibitionId : goupbyMap.keySet()) {
                    certificateUserService.sycnRemoveBackSertificate(
                            goupbyMap.get(exhibitionId).stream().map(Blacklist::getPhoneNumber).collect(Collectors.toList()),
                            goupbyMap.get(exhibitionId).stream().map(Blacklist::getCardNumber).collect(Collectors.toList()),
                            goupbyMap.get(exhibitionId).stream().map(Blacklist::getCompanyId).collect(Collectors.toList()),
                            Arrays.asList(exhibitionId), null);
                }
            }
        }
    }

    @Override
    public void addBlack(Blacklist blacklist) {
        save(blacklist);
        //同步到制证
        if (BlacklistKindEnum.POLICE.eq(blacklist.getKind()) || BlacklistKindEnum.VENUE.eq(blacklist.getKind())) {
            certificateUserService.sycnAddBackSertificate(
                    StringUtils.isNotBlank(blacklist.getPhoneNumber()) ? Arrays.asList(blacklist.getPhoneNumber()) : null,
                    StringUtils.isNotBlank(blacklist.getCardNumber()) ? Arrays.asList(blacklist.getCardNumber()) : null,
                    blacklist.getCompanyId() == null ? null : Arrays.asList(blacklist.getCompanyId()), null);
        } else if (BlacklistKindEnum.EXHIBITION.eq(blacklist.getKind())) {
            certificateUserService.sycnAddBackSertificate(
                    StringUtils.isNotBlank(blacklist.getPhoneNumber()) ? Arrays.asList(blacklist.getPhoneNumber()) : null,
                    StringUtils.isNotBlank(blacklist.getCardNumber()) ? Arrays.asList(blacklist.getCardNumber()) : null,
                    blacklist.getCompanyId() == null ? null : Arrays.asList(blacklist.getCompanyId()),
                    blacklist.getExhibitionId() == null ? null : Arrays.asList(blacklist.getExhibitionId())
            );
        }
    }

    /**
     * 查询整体黑名单
     *
     * @return
     */
    public Map<BlacklistKindEnum, List<Blacklist>> findBlackList(List<Blacklist> blacklists) {
        if (CollectionUtil.isEmpty(blacklists)) {
            BlacklistDTO modelDTO = new BlacklistDTO();
            modelDTO.setIsDeleted(BusinessConstant.NO);
            blacklists = list(modelDTO, null);
        }
        if (CollectionUtil.isEmpty(blacklists)) {
            return null;
        }
        Map<BlacklistKindEnum, List<Blacklist>> map = blacklists.stream().collect(Collectors.groupingBy(s -> s.getKind()));
        //公安黑名单
        List<Blacklist> policeBlackList = map.get(BlacklistKindEnum.POLICE);
        //场馆黑名单
        List<Blacklist> venueBlackList = map.get(BlacklistKindEnum.VENUE);
        //展会黑名单
        List<Blacklist> exhibitionBlackList = map.get(BlacklistKindEnum.EXHIBITION);

        //过滤公安黑名单之后的数据
        venueBlackList = filterBlackList(venueBlackList, policeBlackList);
        exhibitionBlackList = filterBlackList(exhibitionBlackList, policeBlackList);
        //过滤场馆名单之后的数据
        exhibitionBlackList = filterBlackList(exhibitionBlackList, venueBlackList);
        map.put(BlacklistKindEnum.POLICE, policeBlackList);
        map.put(BlacklistKindEnum.VENUE, venueBlackList);
        map.put(BlacklistKindEnum.EXHIBITION, exhibitionBlackList);
        return map;
    }

    /**
     * 过滤list
     *
     * @param blacklistList         需过滤list
     * @param contrastBlacklistList 对比list
     * @return
     */
    public List<Blacklist> filterBlackList(List<Blacklist> blacklistList, List<Blacklist> contrastBlacklistList) {
        if (CollectionUtil.isEmpty(blacklistList) || CollectionUtil.isEmpty(contrastBlacklistList)) {
            return blacklistList;
        }
        List<String> cardNumberList = contrastBlacklistList.stream().map(Blacklist::getCardNumber).collect(Collectors.toList());
        List<String> phoneNumberList = contrastBlacklistList.stream().map(Blacklist::getPhoneNumber).collect(Collectors.toList());
        List<Long> companyIdList = contrastBlacklistList.stream().map(Blacklist::getCompanyId).collect(Collectors.toList());

        List<Long> exhibitionIdList = contrastBlacklistList.stream().map(Blacklist::getExhibitionId).collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(cardNumberList)) {
            blacklistList = blacklistList.stream().filter(s -> !cardNumberList.contains(s.getCardNumber())).collect(Collectors.toList());
        }
        if (CollectionUtil.isNotEmpty(phoneNumberList)) {
            blacklistList = blacklistList.stream().filter(s -> !phoneNumberList.contains(s.getPhoneNumber())).collect(Collectors.toList());
        }
        if (CollectionUtil.isNotEmpty(companyIdList)) {
            blacklistList = blacklistList.stream().filter(s -> !companyIdList.contains(s.getCompanyId())).collect(Collectors.toList());
        }

        if (CollectionUtil.isNotEmpty(exhibitionIdList)) {
            blacklistList = blacklistList.stream().filter(s -> !exhibitionIdList.contains(s.getExhibitionId())).collect(Collectors.toList());
        }


        return blacklistList;
    }

    /**
     * do转vo
     *
     * @param model model
     * @return modelVo
     */
    @Override
    public BlacklistVO doToVo(Blacklist model) {
        BlacklistVO modelVo = new BlacklistVO();
        BeanUtils.copyProperties(model, modelVo);
        modelVo.setId(model.getId());
        return modelVo;
    }

    /**
     * do转vo
     *
     * @param modelList modelList
     * @return list
     */
    @Override
    public List<BlacklistVO> doToVos(List<Blacklist> modelList) {
        if (modelList == null || modelList.isEmpty()) {
            return null;
        }
        List<BlacklistVO> result = new ArrayList<>();
        for (Blacklist model : modelList) {
            result.add(doToVo(model));
        }
        return result;
    }


}
